package com.wangsh.webforward.common.util;

import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.gargoylesoftware.htmlunit.util.NameValuePair;

/**
 * Http工具类的加强版本
 * @author Administrator
 *
 */
public class HttpPlusUtil
{
	/* 使用到HttpUtil的工具类 */
	private HttpUtil httpUtil = new HttpUtil();
	
	/**
	 * 模拟浏览器发送请求
	 * @param urlStr 请求的网址
	 * @param headerMap 请求头
	 * @param paramsMap 请求体
	 * @param responseMap 响应体
	 * @return	返回的是html
	 */
	public String broswerRequest(String urlStr,String method,Map<String, String> headerMap,
			Map<String, String> paramsMap,Map<String, String> responseMap)
	{
		String result = "";
		for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++)
		{
			/* 起始时间戳 */
			long st = System.currentTimeMillis() ; 
			/* 结束时间戳 */
			long ed = 0 ; 
			WebClient webClient = null ; 
			try
			{
				/* 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象 */
				webClient = new WebClient(BrowserVersion.CHROME);
				/* 获取到一些配置信息 */
				WebClientOptions webClientOptions = webClient.getOptions() ; 
				/* 当JS执行出错的时候是否抛出异常, 这里选择不需要 */
				webClientOptions.setThrowExceptionOnScriptError(false);
				/* 当HTTP的状态非200时是否抛出异常, 这里选择不需要 */
				webClientOptions.setThrowExceptionOnFailingStatusCode(false);
				/* 设置activeX插件 */
				webClientOptions.setActiveXNative(false);
				/* 是否启用css */
				webClientOptions.setCssEnabled(false);
				/* 是否启用js(重要) */
				webClientOptions.setJavaScriptEnabled(true);
				/* 设置超时 */
				webClientOptions.setTimeout(ConstatFinalUtil.READ_TIMEOUT);
				/* 是否支持ajax(重要) */
				webClient.setAjaxController(new NicelyResynchronizingAjaxController());
				ConstatFinalUtil.SYS_LOGGER.info("====webClient:{}",webClient);
				/* 准备网址 */
				URL url = new URL(urlStr);
				/* ======设置请求头开始====== */
				//webClient.addRequestHeader("", "");
				for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ;
					String value = me.getValue() + ""; 
					if(!"cookie".equalsIgnoreCase(key))
					{
						webClient.addRequestHeader(key, value);
					}
				}
				/* ======设置请求头结束====== */
				/* ======设置Cookie开始====== */
				String cookie = headerMap.get("cookie");
				/* ======设置Cookie结束====== */
				CookieManager cookieManager = webClient.getCookieManager() ; 
				/* 启用Cookie */
				cookieManager.setCookiesEnabled(true);
				/* 把Cookie拆开 */
				Map<String, String> cookieMap = this.httpUtil.cookieSplit(cookie);
				Calendar calendar = Calendar.getInstance() ; 
				calendar.add(Calendar.MONTH, 1);
				for (Iterator iterator = cookieMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ; 
					String value = me.getValue() + "" ; 
					
					/* 客户端Cookie */
					cookieManager.addCookie(new Cookie(url.getHost(),key,value,"/",calendar.getTime(),false));
					//cookieManager.addCookie(new Cookie(url.getHost(),key,value,"/",6000,true));
				}
				
				/* 增加Cookie */
				/* ======设置请求体开始====== */
				List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
				for (Iterator iterator = paramsMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ;
					String value = me.getValue() + ""; 
					/* 参数和值 */
					NameValuePair nameValuePair = new NameValuePair(key, value);
					paramsList.add(nameValuePair);
				}
				
				WebRequest webRequest = new WebRequest(url);
				if("post".equalsIgnoreCase(method))
				{
					webRequest.setHttpMethod(HttpMethod.POST);
				}else
				{
					webRequest.setHttpMethod(HttpMethod.GET);
				}
				/* 设置请求体 */
				webRequest.setRequestParameters(paramsList);
				/* ======设置请求体结束====== */
				/* 请求网页 */
				HtmlPage htmlPage = webClient.getPage(webRequest);
				result = htmlPage.asXml();
				ConstatFinalUtil.SYS_LOGGER.info("====长度:{};",result.length());
				/* 等待时间 */
				webClient.waitForBackgroundJavaScript(5 * ConstatFinalUtil.SECOND);
				/* 网页内容 */
				result = htmlPage.asXml();
				ConstatFinalUtil.SYS_LOGGER.info("====长度:{};",result.length());
				/* 响应体: */
				WebResponse webResponse = webClient.loadWebResponse(webRequest);
				List<NameValuePair> responseHeaders = webResponse.getResponseHeaders();
				for (Iterator iterator = responseHeaders.iterator(); iterator.hasNext();)
				{
					NameValuePair nameValuePair = (NameValuePair) iterator.next();
					String name = nameValuePair.getName() ; 
					String value = nameValuePair.getValue() ; 
					String valueTar = responseMap.get(name);
					if(valueTar != null)
					{
						/* 说明找到了 */
						value = valueTar + value + ConstatFinalUtil.SPLIT_STR; 
					}
					/* 请求头,请求体 */
					responseMap.put(name, value);
				}
				this.httpUtil.responseHeaderSave(headerMap, responseMap, null);
				ed = System.currentTimeMillis() ; 
				/* 请求成功 */
				break ;
			} catch (Exception e)
			{
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("模拟浏览器请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
			}finally
			{
				if(webClient != null)
				{
					webClient.close();
					webClient = null;
				}
			}
			
			//重试机制
			if("false".equalsIgnoreCase(headerMap.get("retry")))
			{
				/* 默认不重试 */
				break ; 
			}
		}
		return result;
	}
}
